package com.umfwechat.h5.controller.billDetail;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.umfwechat.common.code.RetCode;
import com.umfwechat.common.constant.CacheConsts;
import com.umfwechat.common.constant.CommonConsts;
import com.umfwechat.common.constant.ValueConsts;
import com.umfwechat.common.prop.UmfPropModel;
import com.umfwechat.util.DateTimesUtil;
import com.umfwechat.util.HttpUtil;
import com.umfwechat.util.RedisUtil;
import com.umfwechat.util.ReqMessageUtil;
import com.umfwechat.util.StringUtil;
import com.umpay.sp.model.common.ReqMessage;
import com.umpay.sp.model.common.ResMessage;
import com.umpay.sp.model.settle.SettleStat;
import com.umpay.sp.service.settle.remote.SettleStatServiceRemote;
import com.umpay.sp.service.soopay.remote.PayOrderServiceRemote;
import com.umpay.sp.util.AmountUtil;

/**
 * @ClassName BillDetailsController
 * @desc 账单明细
 * @author liuchunyan
 * @date 2017-05-15上午11:58:18
 * @version 1.0
 */
@Controller
@RequestMapping("/h5/billDetail")
public class BillDetailController {
	private static Logger logger = LoggerFactory.getLogger(BillDetailController.class);

	//查询订单接口
	@Resource
	private PayOrderServiceRemote payOrderServiceRemote;
	
	//查询结算信息接口
	@Resource
	private SettleStatServiceRemote settleStatServiceRemote;
	
	/**
	 * desc:账单明细列表
	 * 
	 * @param reqMessage
	 * @return ResMessage
	 * @throws 
	 * 	 */
	@RequestMapping(value="/getBillDetailList",produces="text/html;charset=UTF-8")
	@ResponseBody
	public String getBillDetailList(HttpServletRequest request, HttpServletResponse response) throws Exception{	
		logger.info("【账单明细列表】开始");
		Map<String, Object> resultMap = new HashMap<String, Object>();
		//参数校验 
		String checkErr = checkParam(request);
		if(!StringUtil.isEmpty(checkErr)){
			return checkErr;
		}
		//报备编号
		String posReportId = request.getParameter(CommonConsts.POS_REPORT_ID);
		//店铺编号
		String storeId = request.getParameter(CommonConsts.STOREID);
		//当前页
		int currentPage = Integer.parseInt(request.getParameter(CommonConsts.CURRENT_PAGE));
		//每页大小
		int pageSize = Integer.parseInt(request.getParameter(CommonConsts.PAGE_SIZE));
		//身份
		int rank = Integer.parseInt(request.getSession().getAttribute(CommonConsts.RANK).toString());
		
		try{
			List<String> payOrderList = new ArrayList<String>();
			//获取最早日期
			String minDateStr = getMinDate(rank);
			//今天日期
			String currentDateStr =  DateTimesUtil.date8(Calendar.getInstance().getTime());
			resultMap.put(CommonConsts.TODAY, currentDateStr);
			//昨天日期
			String yesterdayDateStr = DateTimesUtil.addDays(currentDateStr, -1);
			resultMap.put(CommonConsts.YESTERDAY, yesterdayDateStr);
			
			//查询结束日期
			String endSettleDate = "";
			int loopCnt = 0;
			//今日订单
			String currentPayOrderStr = "";
			//昨日订单
			String yesterdayPayOrderStr = "";
			//当前页是第一页
			if(currentPage == 1){
				//今天的统计，调用订单统计接口
				currentPayOrderStr = getPayOrderStr(posReportId, storeId, currentDateStr);
				if(StringUtil.isEmpty(currentPayOrderStr)){
					resultMap.put(CommonConsts.RETCODE, RetCode.FAIL);
					resultMap.put(CommonConsts.RETMSG, "订单统计失败！");
					return JSONObject.fromObject(resultMap).toString();
				}
				payOrderList.add(currentPayOrderStr);
				
				//昨天的统计，调用订单统计接口
				yesterdayPayOrderStr = getPayOrderStr(posReportId, storeId, yesterdayDateStr);
				if(StringUtil.isEmpty(yesterdayPayOrderStr)){
					resultMap.put(CommonConsts.RETCODE, RetCode.FAIL);
					resultMap.put(CommonConsts.RETMSG, "订单统计失败！");
					return JSONObject.fromObject(resultMap).toString();
				}
				payOrderList.add(yesterdayPayOrderStr);
				
				loopCnt = pageSize - 2;
				endSettleDate = DateTimesUtil.addDays(currentDateStr, -2);
			}else{
				loopCnt = pageSize;
				endSettleDate = DateTimesUtil.addDays(currentDateStr, -(currentPage-1) * loopCnt);
			}
			
			//下一页是否有数据
			boolean hasNextData = false;
			String startSettleDate = DateTimesUtil.addDays(endSettleDate, -loopCnt + 1);
			Map<String, Object> qryMapNext = new HashMap<String, Object>();
			//商户编号
			qryMapNext.put(CommonConsts.MERID, storeId);
			//结束日期
			qryMapNext.put(CommonConsts.END_DATE, DateTimesUtil.addDays(startSettleDate, -1));
			//开始日期
			qryMapNext.put(CommonConsts.START_DATE, minDateStr);
			//处理完成
			qryMapNext.put(CommonConsts.DEAL_STATE, "2"); 
			logger.info("【查询结算】(下一页是否有数据) 入参：" + qryMapNext);
			List<SettleStat> settleStatListNext = settleStatServiceRemote.querySettleStats(qryMapNext);
			logger.info("【查询结算】(下一页是否有数据) 出参：" + settleStatListNext);
			if(settleStatListNext != null && settleStatListNext.size() > 0){
				hasNextData = true;
			}
			
			boolean redisNotExsitFlg = false;
			boolean maxViewFlg = false;
			for(int i=0; i<loopCnt; i++){
				//订单日期 --
				String orderDate = (i==0) ? endSettleDate : DateTimesUtil.addDays(endSettleDate, -i);
				//身份==0(管理员) 身份==1(操作员)
				if(rank == 0 || rank == 1){
					//订单日期<日期期限
					if(orderDate.compareTo(minDateStr) < 0){
						maxViewFlg = true;
						break;
					}
				}
				
				String redisKey = CacheConsts.WX + CacheConsts.BILLDETAIL + storeId + orderDate;
				String payOrderStr = RedisUtil.get(redisKey);
				//缓存中不存在
				if(StringUtil.isEmpty(payOrderStr)){ 
					redisNotExsitFlg = true;
					break;
				}
				//订单信息添加到日统计列表
				payOrderList.add(payOrderStr);
			}
			
			//最多能看 或者 缓存存在
	        if(maxViewFlg || !redisNotExsitFlg){
	        	resultMap.put(CommonConsts.RETCODE, RetCode.SUC);
	    		resultMap.put(CommonConsts.RETMSG, "获取账单明细成功");
	    		resultMap.put(CommonConsts.HAS_NEXT_DATA, hasNextData);
	    		resultMap.put(CommonConsts.RESULTLIST, payOrderList);
	    		logger.info("获取账单明细成功！resultMap = " + resultMap);
	    		return JSONObject.fromObject(resultMap).toString();
	        }
	       
	        //结算查询
	        Map<String, Object> qryMap = new HashMap<String, Object>();
	        //商户编号
			qryMap.put(CommonConsts.MERID, storeId);
			//结束时间
			qryMap.put(CommonConsts.END_DATE, endSettleDate);
			//开始时间
			qryMap.put(CommonConsts.START_DATE, startSettleDate);
			//处理完成
			qryMap.put(CommonConsts.DEAL_STATE, "2"); 
			logger.info("【查询结算】 入参：" + qryMap);
			List<SettleStat> settleStatList = settleStatServiceRemote.querySettleStats(qryMap);
			logger.info("【查询结算】 出参：" + settleStatList);
			
			if((settleStatList == null || settleStatList.size() == 0) && !hasNextData){
				if(payOrderList.size()>0){
					logger.info("获取交易明细列表成功！");
					resultMap.put(CommonConsts.RETMSG, "获取交易明细列表成功");
				}else{
					logger.info("无账单明细！");
					resultMap.put(CommonConsts.RETMSG, "无账单明细！");
				}
				resultMap.put(CommonConsts.RETCODE, RetCode.SUC);
				resultMap.put(CommonConsts.HAS_NEXT_DATA, hasNextData);
	    		resultMap.put(CommonConsts.RESULTLIST, payOrderList);
	    		logger.info("获取交易明细列表 resultMap = " + resultMap);
				return JSONObject.fromObject(resultMap).toString();
			} 
			
			//初期化日统计列表
			payOrderList = new ArrayList<String>();
			if(!StringUtil.isEmpty(currentPayOrderStr)){
				payOrderList.add(currentPayOrderStr);	
			}
			if(!StringUtil.isEmpty(yesterdayPayOrderStr)){
				payOrderList.add(yesterdayPayOrderStr);
			}
			
			//编辑输出列表
			List<String> editList = editSettleList(storeId, loopCnt, endSettleDate, minDateStr, settleStatList);
			payOrderList.addAll(editList);
			
			resultMap.put(CommonConsts.RETCODE, RetCode.SUC);
			resultMap.put(CommonConsts.RETMSG, "获取交易明细列表成功");
			resultMap.put(CommonConsts.HAS_NEXT_DATA, hasNextData);
			resultMap.put(CommonConsts.RESULTLIST, payOrderList);
			logger.info("获取账单明细成功！resultMap = " + resultMap); 
			return JSONObject.fromObject(resultMap).toString();
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("获取账单明细失败",e);
			resultMap.put(CommonConsts.RETCODE, RetCode.FAIL);
			resultMap.put(CommonConsts.RETMSG, "获取账单明细失败");
			return JSONObject.fromObject(resultMap).toString();
		}
	}
	
	/**
	 * 参数校验
	 * 
	 * @param request
	 * @return
	 */
	private String checkParam(HttpServletRequest request){
		Map<String, Object> resultMap = new HashMap<String, Object>();
		String storeId = request.getParameter(CommonConsts.STOREID);
		String pageSizeStr = request.getParameter(CommonConsts.PAGE_SIZE);
		String currentPageStr = request.getParameter(CommonConsts.CURRENT_PAGE);
		//身份
		String rankStr = "";
		if(request.getSession().getAttribute(CommonConsts.RANK) != null){
			rankStr = request.getSession().getAttribute(CommonConsts.RANK).toString();
		}
		
		if(StringUtil.isEmpty(storeId)){
			logger.info("店铺编号不能为空！"); 
			resultMap.put(CommonConsts.RETCODE, RetCode.FAIL);
			resultMap.put(CommonConsts.RETMSG, "店铺编号不能为空！");
			return JSONObject.fromObject(resultMap).toString();
		}
		if(StringUtil.isEmpty(pageSizeStr) 
				|| Integer.parseInt(pageSizeStr) == 0){
			logger.info("每页条数必须大于0！");
			resultMap.put(CommonConsts.RETCODE, RetCode.FAIL);
			resultMap.put(CommonConsts.RETMSG, "每页条数必须大于0！");
			return JSONObject.fromObject(resultMap).toString();
		}
		if(StringUtil.isEmpty(currentPageStr) 
				|| Integer.parseInt(currentPageStr) == 0){
			logger.info("当前页数必须大于0！");
			resultMap.put(CommonConsts.RETCODE, RetCode.FAIL);
			resultMap.put(CommonConsts.RETMSG, "当前页数必须大于0！");
			return JSONObject.fromObject(resultMap).toString();
		}
		if(StringUtil.isEmpty(rankStr)){
			logger.info("身份不能为空！");
			resultMap.put(CommonConsts.RETCODE, RetCode.FAIL);
			resultMap.put(CommonConsts.RETMSG, "身份不能为空！");
			return JSONObject.fromObject(resultMap).toString();
		}
		
		return null;
	}
	
	/**
	 * 获取最早日期
	 * 
	 * @param rank 身份
	 * @return
	 */
	private String getMinDate(int rank){
		String minDateStr = "";
		//身份==0(管理员)
		if(rank == 0){
			//最近6个月
			Calendar preSixMonthCalendar = Calendar.getInstance();
			preSixMonthCalendar.add(Calendar.MONTH, -5);
			preSixMonthCalendar.set(Calendar.DATE, 1);
			minDateStr = DateTimesUtil.date8(preSixMonthCalendar.getTime());
			
			//身份==1(操作员)
		}else if(rank == 1){
			//最近30天
			Calendar preMonthCalendar = Calendar.getInstance();
			preMonthCalendar.add(Calendar.DATE, -29);
			minDateStr = DateTimesUtil.date8(preMonthCalendar.getTime());
		}
		return minDateStr;
	}
	
	/**
	 * 订单统计
	 * 
	 * @param posReportId 报备编号
	 * @param storeId 店铺编号
	 * @param orderDate 交易日期
	 * @return
	 * @throws Exception
	 */
	private String getPayOrderStr(String posReportId, String storeId, String orderDate) throws Exception{
		
		ReqMessage reqMessage = ReqMessageUtil.makeSpReq();
		reqMessage.put(CommonConsts.QRYTYPE, "1"); //查询类型
		reqMessage.put(CommonConsts.MERID, storeId); //商户编号
		reqMessage.put(CommonConsts.ORDERDATE, orderDate);//订单日期
		logger.info("【订单统计】入参：" + reqMessage);
		ResMessage payOrderRes = payOrderServiceRemote.statPayOrder(reqMessage);
		logger.info("【订单统计】出参：payOrderRes=" + payOrderRes);
		if(!RetCode.SUCCESS.equals(payOrderRes.getRetCode())){
			logger.info("订单统计失败！" + payOrderRes.getRetMsg());
			return null;
		}
		 
		//pos金额
		String posAmt = "0";
		//pos笔数
		String posNum = "0";
		if(StringUtil.isNotEmpty(posReportId)){
			//获取pos的统计金额和笔数
			Map<String, Object> posDataMap = getPosAmtNum(storeId, orderDate);
			if(!RetCode.SUCCESS.equals(posDataMap.get(CommonConsts.RETCODE))){
				logger.info("商户交易统计查询失败！" + posDataMap.get(CommonConsts.RETMSG));
				return null;
			}
			//pos金额
			posAmt = posDataMap.get(CommonConsts.TRAN_AMTS).toString();
			//pos笔数
			posNum = posDataMap.get(CommonConsts.TRAN_COUNT).toString();
		}
		
		//订单金额
		String successAmt = payOrderRes.getValue(CommonConsts.SUCCESS_AMT).toString();
		//金额总计 = 订单金额+pos金额 
		String dealAmt = new BigDecimal(successAmt).add(new BigDecimal(posAmt)).toString();
		
		//订单笔数
		String successNum = payOrderRes.getValue(CommonConsts.SUCCESS_NUM).toString();
		//金额总计 = 订单笔数 +pos笔数
		int dealNum = Integer.parseInt(successNum) + Integer.parseInt(posNum);
				
		//订单信息
		Map<String,Object> dataMap =  new HashMap<String,Object>();
		//订单日期
		dataMap.put(CommonConsts.ORDERDATE, orderDate);
		//成功金额(分转元)
		dataMap.put(CommonConsts.DEAL_AMT, AmountUtil.Cent2Dollar2(dealAmt));
		//成功笔数
		dataMap.put(CommonConsts.DEAL_NUM, dealNum);
		return JSONObject.fromObject(dataMap).toString();
	}
	
	/**
	 * 获取商户交易统计
	 * 
	 * @param storeId 店铺编号
	 * @param orderDate 交易日期
	 * @return
	 * @throws Exception
	 */
	private Map<String,Object> getPosAmtNum(String storeId, String orderDate) throws Exception{
		//商户交易统计查询接口 /offline-serv1/0903
		String url = UmfPropModel.INSTANCE.getPropValue("saas.pos.offlineserv10903");
		ReqMessage reqMessage = ReqMessageUtil.makeSpReq();
		Map<String, Object> reqMap = new HashMap<String, Object>();
		reqMap.put(CommonConsts.RPID, reqMessage.getRpid());
		reqMap.put(CommonConsts.REQDATE, reqMessage.getReqDate());
		reqMap.put(CommonConsts.REQTIME, reqMessage.getReqTime());
		//参数数据来源
		reqMap.put(CommonConsts.DATASOURCE, CommonConsts.SAAS);
		//商户号
		reqMap.put(CommonConsts.MERCHANTID, storeId);
		//交易日期
		reqMap.put(CommonConsts.LOCALSYSDATE, orderDate);
		
		logger.info("【商户交易统计】路径：" + url + " 入参：" + reqMap);
		Map<String, Object> dataMap = HttpUtil.httpPostForm2Xml(url, reqMap);
		logger.info("【商户交易统计】出参：" + dataMap);
		return dataMap;
	}
	
	/**
	 * 编辑结算输出列表
	 * 
	 * @param storeId 店铺编号
	 * @param loopCnt 循环次数
	 * @param endSettleDate 结束结算日期
	 * @param minDateStr 最小日期
	 * @param settleStatList 结算列表
	 * @return
	 */
	private List<String> editSettleList(String storeId, int loopCnt, String endSettleDate,
			String minDateStr, List<SettleStat> settleStatList){
		List<String> payOrderList = new ArrayList<String>();
		for(int i=0; i<loopCnt; i++){
			boolean findFlg = false;
			String orderDate = (i==0) ? endSettleDate : DateTimesUtil.addDays(endSettleDate, -i);
			if(orderDate.compareTo(minDateStr) < 0){
				break;
			}
			Map<String, Object> dataMap = new HashMap<String, Object>();
			if(settleStatList != null && settleStatList.size() > 0){
				for(SettleStat settleStat : settleStatList){
					//交易日期
					if(orderDate.equals(settleStat.getSettleDate())){
						//交易日期
						dataMap.put(CommonConsts.ORDERDATE, orderDate);
						//日总交易额（分转元）
						dataMap.put(CommonConsts.DEAL_AMT, AmountUtil.Cent2Dollar2(settleStat.getAmount()));
						//日总笔数
						dataMap.put(CommonConsts.DEAL_NUM, settleStat.getTransNum());
						findFlg = true;
						break;
					}
				}
			}
			
			if(!findFlg){
				//交易日期
				dataMap.put(CommonConsts.ORDERDATE, orderDate);
				//日总交易额
				dataMap.put(CommonConsts.DEAL_AMT, "0.00");
				//日总笔数
				dataMap.put(CommonConsts.DEAL_NUM, 0);
			}
			
			//添加到列表
			String payOrderStr = JSONObject.fromObject(dataMap).toString();
			payOrderList.add(payOrderStr);
			
			//存到缓存
			String redisKey = CacheConsts.WX + CacheConsts.BILLDETAIL + storeId + orderDate;
			RedisUtil.set(redisKey, ValueConsts.ONE_WEEK, payOrderStr);
		}
		
		return payOrderList;
	}
	
}